package com.gitee.qdbp.general.common.biz.sms.service;

import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.general.common.api.sms.model.ISmsTemplate;
import com.gitee.qdbp.general.common.error.GeneralErrorCode;
import com.gitee.qdbp.tools.http.HttpException;
import com.gitee.qdbp.tools.http.HttpTools;

/**
 * 江苏美圣短信服务接口<br>
 * http://www.jsmsxx.com/
 *
 * @author zhaohuihua
 * @version 151119
 */
// @Service // 这个Service在spring的xml文件中配置, 因为有些平台不需要短信功能
public class JsmsSmsService extends BaseSmsService {

    private static final Logger log = LoggerFactory.getLogger(JsmsSmsService.class);

    public JsmsSmsService() {
        this.properties = "settings/sms/sms.jsms.txt";
    }

    @Override
    @PostConstruct
    public void init() {
        super.init();
    }

    @Override
    public String send(String phone, ISmsTemplate template, Object... args) throws ServiceException {

        utils.check(phone, template.name());

        String msg = "Failed to send Short Message.";

        String url = config.getString("sms.service.url");

        // method=sendMsg&username=JSM40001&password=123456&veryCode=453245
        // &mobile=15951977097&content=@1@=李先生,@2@=您好,@3@=928371&msgtype=2&tempid=JSM4001-000&code=UTF-8
        StringBuilder text = new StringBuilder();
        for (int i = 0; i < args.length; i++) {
            if (i > 0) {
                text.append(",");
            }
            text.append("@").append(i + 1).append("@");
            text.append("=").append(args[i]);
        }

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("method", "sendMsg");
        params.put("username", config.getString("auth.username"));
        params.put("password", config.getString("auth.password"));
        params.put("veryCode", config.getString("auth.verycode"));
        params.put("mobile", phone);
        params.put("content", text.toString());
        params.put("msgtype", 2);
        params.put("tempid", config.getString("template." + template.name()));
        params.put("code", "utf-8");

        // <sms><mt><status>0</status><msgid>816f333305664fb9bdd8c1bc96ae12b8</msgid></mt></sms>
        String xml;
        try {
            xml = HttpTools.form.post(url, params);
        } catch (HttpException e) {
            log.error(msg + " HTTP request exception.", e);
            throw new ServiceException(GeneralErrorCode.SMS_SEND_ERROR);
        }

        Mt mt;
        try {
            JAXBContext context = JAXBContext.newInstance(Sms.class);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            Sms sms = (Sms) unmarshaller.unmarshal(new StringReader(xml));
            mt = sms.getMt();
        } catch (JAXBException e) {
            log.error(msg + " HTTP request success, but XML parse error.\n\t" + xml, e);
            throw new ServiceException(GeneralErrorCode.SMS_SEND_ERROR);
        }

        String status = mt.getStatus();

        String succ = config.getString("resultcode.success");

        if (status == null || !status.equals(succ)) {
            int index = status.indexOf('#');
            if (index < 0) {
                String desc = config.getString("resultcode.send." + status, false);
                log.error(msg + " result code is {} - {}", status, desc);
            } else {
                // 110#(敏感词A,敏感词B)
                String code = status.substring(0, index);
                String words = status.substring(index + 1);
                String desc = config.getString("resultcode.send." + code, false);
                log.error(msg + " result code is {} - {} - {}", status, desc, words);
            }
            throw new ServiceException(GeneralErrorCode.SMS_SEND_ERROR);
        }

        return mt.getMsgid();
    }

    @Override
    public Double balances() throws ServiceException {

        String msg = "Failed to get sms balances.";

        String url = config.getString("sms.service.url");

        // method=getAmount&username=JSM40001&password=123456&veryCode=453245
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("method", "getAmount");
        params.put("username", config.getString("auth.username"));
        params.put("password", config.getString("auth.password"));
        params.put("veryCode", config.getString("auth.verycode"));

        String xml;
        try {
            xml = HttpTools.form.post(url, params);
        } catch (HttpException e) {
            log.error(msg + " HTTP request exception.", e);
            throw new ServiceException(GeneralErrorCode.SMS_BALANCES_ERROR);
        }

        Mt mt;
        try {
            JAXBContext context = JAXBContext.newInstance(Sms.class);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            Sms sms = (Sms) unmarshaller.unmarshal(new StringReader(xml));
            mt = sms.getMt();
        } catch (JAXBException e) {
            log.error(msg + " HTTP request success, but XML parse error.\n\t" + xml, e);
            throw new ServiceException(GeneralErrorCode.SMS_BALANCES_ERROR);
        }

        String status = mt.getStatus();

        String succ = config.getString("resultcode.success");

        if (status == null || !status.equals(succ)) {
            String desc = config.getString("resultcode.balances." + status, false);
            log.error(msg + " result code is {} - {}", status, desc);
            throw new ServiceException(GeneralErrorCode.SMS_BALANCES_ERROR);
        }

        return mt.getAccount();
    }

    /**
     * 用于解析短信接口返回的XML的实体类
     *
     * @author zhaohuihua
     * @version 151120
     */
    @XmlRootElement
    static class Sms {

        private Mt mt;

        public void setMt(Mt mt) {
            this.mt = mt;
        }

        public Mt getMt() {
            return mt;
        }
    }

    /**
     * 用于解析短信接口返回的XML的实体类
     *
     * @author zhaohuihua
     * @version 151120
     */
    static class Mt {

        private String status;

        private String msgid;

        private Double account;

        public void setStatus(String status) {
            this.status = status;
        }

        public String getStatus() {
            return status;
        }

        public String getMsgid() {
            return msgid;
        }

        public void setMsgid(String msgid) {
            this.msgid = msgid;
        }

        public Double getAccount() {
            return account;
        }

        public void setAccount(Double account) {
            this.account = account;
        }

    }

}
